﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Kimd.Common
{
    public class CompileHelper : SingletonProvider<CompileHelper>
    {
        public bool Compile(string name, string flowName, string assemblyName, int compileIndex, out List<CompileErrInfo> lines)
        {
            lines = new List<CompileErrInfo>();
            // 文件路径
            string doclib = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            string srccodePath = PathHelper.GetConfigPath("Flow") + name + "\\" + flowName + "\\Temp\\" + assemblyName + ".cs";
            if (!Directory.Exists(PathHelper.GetConfigPath("Flow") + name + "\\" + flowName + "\\Temp"))
                Directory.CreateDirectory(PathHelper.GetConfigPath("Flow") + name + "\\" + flowName + "\\Temp");

            CodeDomProvider provider = CodeDomProvider.CreateProvider("cs");
            // 编译参数
            CompilerParameters p = new CompilerParameters();
            // 输出文件
            p.OutputAssembly = PathHelper.GetConfigPath("Flow") + name + "\\" + flowName + "\\Temp\\" + $"{ assemblyName}_{compileIndex}" + ".dll";
            string baseDir = AppDomain.CurrentDomain.BaseDirectory;
            // 添加引用的程序集
            p.ReferencedAssemblies.Add(baseDir + "Kimd.Data.dll");
            p.ReferencedAssemblies.Add(baseDir + "Kimd.Common.dll");
            p.ReferencedAssemblies.Add(baseDir + "Kimd.Communication.dll");
            p.ReferencedAssemblies.Add(baseDir + "Kimd.Logic.dll");
            p.ReferencedAssemblies.Add(baseDir + "Kimd.Machine.dll");
            p.ReferencedAssemblies.Add(baseDir + "Kimd.Vision.dll");
            p.ReferencedAssemblies.Add(baseDir + "StepLibs\\Kimd.Step.dll");
            p.ReferencedAssemblies.Add("System.dll");
            p.ReferencedAssemblies.Add("System.Core.dll");
            p.ReferencedAssemblies.Add("System.Xml.dll");
            p.ReferencedAssemblies.Add(baseDir + "System.Windows.Forms.dll");
            p.ReferencedAssemblies.Add(baseDir + "System.Drawing.dll");
            lines.Clear();
            // 编译
            CompilerResults res = provider.CompileAssemblyFromFile(p, srccodePath);
            // 检查编译结果
            if (res.Errors.Count == 0)
            {
                compileIndex++;
                lines.Add(new CompileErrInfo("编译成功。"));
                // 获取刚刚编译的程序集信息
                Assembly outputAss = res.CompiledAssembly;
                lines.Add(new CompileErrInfo($"程序集全名：{outputAss.FullName}"));
                // 位置
                lines.Add(new CompileErrInfo($"程序集位置：{outputAss.Location}"));
                return true;
            }
            else
            {
                lines.Add(new CompileErrInfo("发生错误，详见以下内容：\r\n"));
                foreach (CompilerError er in res.Errors)
                {
                    CompileErrInfo cei = new CompileErrInfo($"行{er.Line}，列{er.Column}，错误号{er.ErrorNumber}，错误信息：{er.ErrorText}");
                    cei.IsMessage = false;
                    cei.LineNo = er.Line;
                    cei.ColumnNo = er.Column;
                    cei.ErrorNumber = er.ErrorNumber;
                    cei.ErrorText = er.ErrorText;
                    lines.Add(cei);
                }
                return false;
            }
        }
    }

    public class CompileErrInfo
    {
        public bool IsMessage { get; set; }
        public string ErrMessage { get; set; }
        public int LineNo { get; set; }
        public int ColumnNo { get; set; }
        public string ErrorNumber { get; set; }
        public string ErrorText { get; set; }

        public CompileErrInfo(string info)
        {
            this.ErrMessage = info;
            this.IsMessage = true;
        }
    }
}
